#include "gameFunction.hh"

namespace gamefunction {
    std::vector<ICharacter*> getFightVec(std::vector<ICharacter*>& hero_team, std::vector<ICharacter*>& enemy_team) {
        std::vector<ICharacter*> round_vec;

        for (auto* obj : hero_team) {
            obj->modifyRoundSpeed(randomFunc::get_Random_Num(obj->getSpeed() - 2, obj->getSpeed() + 3));
            round_vec.push_back(obj);
        }
    
        for (auto* obj : enemy_team) {
            obj->modifyRoundSpeed(randomFunc::get_Random_Num(obj->getSpeed() - 2, obj->getSpeed() + 3));
            round_vec.push_back(obj);
        }
    
        for (auto* obj : round_vec) {
            std::sort(round_vec.begin(), round_vec.end(), [](const ICharacter* a, const ICharacter* b) {  
                return a->getRoundSpeed() > b->getRoundSpeed(); // 降序排列  
            });  

        }

        return round_vec;
    }

    void fight_round(std::vector<ICharacter*>& fight_vec, std::vector<ICharacter*>& hero_team, std::vector<ICharacter*>& enemy_team, unsigned rounds) {
        unsigned skill_num;
        unsigned skill_target;
        
        for (auto* obj : fight_vec) {
            IO::clearTerminal();
            std::cout << "----------------round" << rounds << "--------------\n";
            IO::display_teams_massage(hero_team, enemy_team);
            if (!obj->getRoundFinsh()) {
                std::cout << "----------------" << obj->getName() << "'s round--------------\n";
                skill_num = obj->getSkillName();
                if (skill_num == 1) {
                    skill_target = obj->getskill1Target();
                    if (auto* h = dynamic_cast<Ahero*>(obj)) {
                        h->skill1(enemy_team, hero_team, skill_target);
                    }
                    if (auto* e = dynamic_cast<Aenemy*>(obj)) {
                        e->skill1(hero_team, enemy_team, skill_target);
                    }
                } else {
                    skill_target = obj->getskill2Target();
                    if (auto* h = dynamic_cast<Ahero*>(obj)) {
                        h->skill2(enemy_team, hero_team, skill_target);
                    }
                    if (auto* e = dynamic_cast<Aenemy*>(obj)) {
                        e->skill2(hero_team, enemy_team, skill_target);
                    }
                }
                IO::getString("Enter any keys to continue.\n");
            }
            obj->sitRoundFinsh(true);
        }

        for (int i = enemy_team.size() - 1; i >= 0; --i) {
            if (!enemy_team[i]->isAlive()) {
                delete enemy_team[i];
                enemy_team.erase(enemy_team.begin() + i);
            }
        }

        for (int i = hero_team.size() - 1; i >= 0; --i) {
            if (!hero_team[i]->isAlive()) {
                delete hero_team[i];
                hero_team.erase(hero_team.begin() + i);
            }
        }

        for (auto* obj : hero_team) {
            obj->sitRoundFinsh(false);
        }

        for (auto* obj : enemy_team) {
            obj->sitRoundFinsh(false);
        }

    }

    void hole_fight(std::vector<ICharacter*>& hero_team, std::vector<ICharacter*>& enemy_team) {
        std::vector<ICharacter*> round_vec;
        bool fight_finsh = false;
        unsigned rounds = 1;

        while (!fight_finsh)
        {   
            IO::display_teams_massage(hero_team, enemy_team);
            round_vec = getFightVec(hero_team, enemy_team);
            fight_round(round_vec, hero_team, enemy_team, rounds);
            if (enemy_team.empty() || hero_team.empty()) {
                fight_finsh = true;
            }
            round_vec.clear();
            rounds += 1;
        }

        if (!round_vec.empty()) {
            round_vec.clear();
        }

        if (!enemy_team.empty()) {
            for (auto* obj : enemy_team) delete obj;
            enemy_team.clear();
        }

        IO::clearTerminal();
        std::cout << "Fight finsh.\n";
        if (hero_team.empty()) {
            std::cout << "All heros died.\n";
        }
        IO::getString("Enter any keys to continue.");
    }

    std::vector<ICharacter*> selectHeroes() {
        std::vector<ICharacter*> selected_heroes;

        // 创建临时英雄对象用于显示信息
        std::vector<ICharacter*> temp_heroes = {
            new heros::highwayman("Highwayman", 0),
            new heros::Jester("Jester", 0),
            new heros::Crusader("Crusader", 0),
            new heros::Houndmaster("Houndmaster", 0),
            new heros::Bounty_Hunter("Bounty Hunter", 0),
            new heros::Leper("Leper", 0),
            new heros::Vestal("Vestal", 0),
            new heros::Plague_Doctor("Plague Doctor", 0)
        };

        // 选择四个英雄
        for (int i = 0; i < 4; ++i) {
            IO::clearTerminal();
            for (size_t i = 0; i < temp_heroes.size(); ++i) {
                std::cout << (i + 1) << ". " << temp_heroes[i]->getName() << "\n"
                          << "   " << temp_heroes[i]->getDescription() << "\n\n";
            }
            std::cout << "Enter 1-8 to choose hero\n";
            unsigned choice = IO::getUnsignedInt(1, 8, "Choose hero in postion " + std::to_string(i+1));
            ICharacter* new_hero = nullptr;
            switch (choice) {
                case 1: new_hero = new heros::highwayman("Highwayman", i); break;
                case 2: new_hero = new heros::Jester("Jester", i); break;
                case 3: new_hero = new heros::Crusader("Crusader", i); break;
                case 4: new_hero = new heros::Houndmaster("Houndmaster", i); break;
                case 5: new_hero = new heros::Bounty_Hunter("Bounty Hunter", i); break;
                case 6: new_hero = new heros::Leper("Leper", i); break;
                case 7: new_hero = new heros::Vestal("Vestal", i); break;
                case 8: new_hero = new heros::Plague_Doctor("Plague Doctor", i); break;
                default: new_hero = new heros::highwayman("Highwayman", i); break; // 输入已验证，无需处理
            }
            selected_heroes.push_back(new_hero);
        }

        
        // 清理临时对象
        for (auto* hero : temp_heroes) {
            delete hero;
            hero = nullptr;
        }

        return selected_heroes;
    }

    std::vector<ICharacter*> enemy_team_1() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Pelagic_Grouper("Pelagic Grouper", 0);
        ICharacter* new_enemy_2 = new enemys::Pelagic_Grouper("Pelagic Grouper", 1);
        ICharacter* new_enemy_3 = new enemys::Pelagic_Grouper("Pelagic Grouper", 2);
        ICharacter* new_enemy_4 = new enemys::Pelagic_Grouper("Pelagic Grouper", 3);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);
        enemy_team.push_back(new_enemy_4);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_2() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Pelagic_Grouper("Pelagic Grouper", 0);
        ICharacter* new_enemy_2 = new enemys::Pelagic_Guardian("Pelagic Guardian", 1);
        ICharacter* new_enemy_3 = new enemys::Pelagic_Shaman("Pelagic Shaman", 2);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);

        return enemy_team;
    }

    std::vector<ICharacter*> enemy_team_3() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Brigand_Bloodletter("Brigand Bloodletter", 0);
        ICharacter* new_enemy_2 = new enemys::Brigand_Cutthroat("Brigand Cutthroat", 1);
        ICharacter* new_enemy_3 = new enemys::Brigand_Fusilier("Brigand Fusilier", 2);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_4() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Carrion_Eater("Carrion Eater", 0);
        ICharacter* new_enemy_2 = new enemys::Carrion_Eater("Carrion Eater", 1);
        ICharacter* new_enemy_3 = new enemys::Carrion_Eater("Carrion Eater", 2);
        ICharacter* new_enemy_4 = new enemys::Carrion_Eater("Carrion Eater", 3);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);
        enemy_team.push_back(new_enemy_4);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_5() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Swine_Chopper("Swine Chopper", 0);
        ICharacter* new_enemy_2 = new enemys::Carrion_Eater("Carrion Eater", 1);
        ICharacter* new_enemy_3 = new enemys::Swine_Slasher("Swine Slasher", 2);
        ICharacter* new_enemy_4 = new enemys::Swine_Drummer("Swine Drummer", 3);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);
        enemy_team.push_back(new_enemy_4);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_6() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Bone_Defender("Bone Defender", 0);
        ICharacter* new_enemy_2 = new enemys::Bone_Soldier("Bone Soldier", 1);
        ICharacter* new_enemy_3 = new enemys::Bone_Courtier("Bone Courtier", 2);
        ICharacter* new_enemy_4 = new enemys::Bone_Arbalist("Bone Arbalist", 3);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);
        enemy_team.push_back(new_enemy_4);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_7() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Cultist_Brawler("Cultist_Brawler", 0);
        ICharacter* new_enemy_2 = new enemys::Cultist_Brawler("Cultist_Brawler", 1);
        ICharacter* new_enemy_3 = new enemys::Cultist_Acolyte("Cultist_Acolyte", 2);
        ICharacter* new_enemy_4 = new enemys::Madman("Madman", 3);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);
        enemy_team.push_back(new_enemy_4);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_8() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Bone_Defender("Bone Defender", 0);
        ICharacter* new_enemy_2 = new enemys::Bone_Soldier("Bone Soldier", 1);
        ICharacter* new_enemy_3 = new enemys::Bone_Soldier("Bone Soldier", 2);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_9() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Cultist_Brawler("Cultist Brawler", 0);
        ICharacter* new_enemy_2 = new enemys::Cultist_Brawler("Cultist Brawler", 1);
        ICharacter* new_enemy_3 = new enemys::Bone_Arbalist("Bone Arbalist", 2);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);
        enemy_team.push_back(new_enemy_3);

        return enemy_team;
    }
    std::vector<ICharacter*> enemy_team_10() {
        std::vector<ICharacter*> enemy_team;

        ICharacter* new_enemy_1 = new enemys::Brigand_Cutthroat("Brigand Cutthroat", 0);
        ICharacter* new_enemy_2 = new enemys::Brigand_Cutthroat("Brigand Cutthroat", 1);

        enemy_team.push_back(new_enemy_1);
        enemy_team.push_back(new_enemy_2);

        return enemy_team;
    }

    std::vector<ICharacter*> get_random_fight() {
        int random_num = randomFunc::get_Random_Num(1, 10);
        std::vector<ICharacter*> enemy_team;

        switch (random_num) {
            case 1: enemy_team = enemy_team_1(); break;
            case 2: enemy_team = enemy_team_2(); break;
            case 3: enemy_team = enemy_team_3(); break;
            case 4: enemy_team = enemy_team_4(); break;
            case 5: enemy_team = enemy_team_5(); break;
            case 6: enemy_team = enemy_team_6(); break;
            case 7: enemy_team = enemy_team_7(); break;
            case 8: enemy_team = enemy_team_8(); break;
            case 9: enemy_team = enemy_team_9(); break;
            case 10: enemy_team = enemy_team_10(); break;
            default: enemy_team = enemy_team_10(); break; // 输入已验证，无需处理
        }
        return enemy_team;
    }

    void hot_spring(std::vector<ICharacter*> hero_team) {
        unsigned choice = IO::getUnsignedInt(1, 2, "There's a hot spring with steam.\nEnter 1 to ignore.\nEnter 2 to do something.\n");
        if (choice == 2) {
            for (auto* obj : hero_team) {
                if (auto* h = dynamic_cast<Ahero*>(obj)) {
                    if (randomFunc::get_persent_bool(95)) {
                        h->stressHealing(20);
                        h->healing(h->getMaxHealth() / 10);
                        std::cout << obj->getName() << "'s stress decreased " << 20 << " .\n";
                        std::cout << obj->getName() << "'s hp increased " << (h->getMaxHealth() / 10) << " .\n";
                    } else {
                        std::cout << "The water seems too hot for " << obj->getName() << " .\n";
                        h->takeStress(10);
                        h->takeDamage(h->getMaxHealth() / 5);
                        std::cout << obj->getName() << "'s stress increased" << 20 << " .\n";
                        std::cout << obj->getName() << "'s hp decreased " << (h->getMaxHealth() / 10) << " .\n";
                    }
                } 
            }
        } else {
            std::cout << "Nothing happen...\n";
        }
        IO::getString("Enter anything to continue.\n");
    }
}